package cn.edu.sdjzu.knoverse.repository;

import cn.edu.sdjzu.knoverse.model.entity.kg.KnowledgeNode;
import cn.edu.sdjzu.knoverse.model.entity.kg.CourseNode;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Set;

@Repository
public interface KnowledgeRepository extends Neo4jRepository<KnowledgeNode, Long> {

    /**
     * 条件查询知识点
     * @param name 知识点名称
     * @param summary 知识点摘要
     * @param level 知识点级别
     * @param pageable 分页参数
     * @return 符合条件的知识点分页数据
     */
    @Query(value = "MATCH (k:Knowledge) " +
            "WHERE " +
            "($name IS NULL OR k.name CONTAINS $name) AND " +
            "($summary IS NULL OR k.summary CONTAINS $summary) AND " +
            "($level IS NULL OR k.level = $level) " +
            "RETURN k",
            countQuery = "MATCH (k:Knowledge) " +
                    "WHERE " +
                    "($name IS NULL OR k.name CONTAINS $name) AND " +
                    "($summary IS NULL OR k.summary CONTAINS $summary) AND " +
                    "($level IS NULL OR k.level = $level) " +
                    "RETURN count(k)")
    Page<KnowledgeNode> findByConditions(@Param("name") String name, 
                                     @Param("summary") String summary, 
                                     @Param("level") Integer level, 
                                     Pageable pageable);

    /**
     * 根据课程ID查找知识点
     * @param courseId 课程ID
     * @return 该课程下的所有知识点
     */
    @Query("MATCH (c:Course)-[:COURSE_KNOWLEDGE]->(k:Knowledge) " +
           "WHERE c.nodeId = $courseId " +
           "RETURN k")
    Set<KnowledgeNode> findByCourseId(Long courseId);
    
    /**
     * 创建课程与知识点的关系
     * @param courseId 课程ID
     * @param knowledgeId 知识点ID
     * @param name 关系名称
     * @param description 关系描述
     */
    @Query("MATCH (c:Course) WHERE c.nodeId = $courseId " +
           "MATCH (k:Knowledge) WHERE k.nodeId = $knowledgeId " +
           "MERGE (c)-[r:COURSE_KNOWLEDGE {name: $name, description: $description}]->(k)")
    void createCourseKnowledgeRelationship(Long courseId, Long knowledgeId, String name, String description);

    /**
     * 删除知识点的所有前置知识点关系
     * @param knowledgeId 知识点ID
     */
    @Query("MATCH (k1:Knowledge)-[r:PRE_KNOWLEDGE]->(k2:Knowledge) WHERE k1.nodeId = $knowledgeId DELETE r")
    void deletePreKnowledgeRelationships(Long knowledgeId);
    
    /**
     * 创建前置知识点关系
     * @param knowledgeId 当前知识点ID
     * @param preKnowledgeId 前置知识点ID
     * @param name 关系名称
     * @param description 关系描述
     */
    @Query("MATCH (k1:Knowledge) WHERE k1.nodeId = $knowledgeId " +
           "MATCH (k2:Knowledge) WHERE k2.nodeId = $preKnowledgeId " +
           "MERGE (k1)-[r:PRE_KNOWLEDGE {name: $name, description: $description}]->(k2)")
    void createPreKnowledgeRelationship(Long knowledgeId, Long preKnowledgeId, String name, String description);
    
    /**
     * 获取知识点的所有前置知识点
     * @param knowledgeId 知识点ID
     * @return 前置知识点列表
     */
    @Query("MATCH (k1:Knowledge)-[r:PRE_KNOWLEDGE]->(k2:Knowledge) WHERE k1.nodeId = $knowledgeId RETURN k2")
    Set<KnowledgeNode> findPreKnowledge(Long knowledgeId);
    
    /**
     * 检查两个知识点之间是否存在前置知识点关系
     * @param knowledgeId 知识点ID
     * @param preKnowledgeId 前置知识点ID
     * @return 存在返回true，否则返回false
     */
    @Query("MATCH (k1:Knowledge) WHERE k1.nodeId = $knowledgeId " +
           "MATCH (k2:Knowledge) WHERE k2.nodeId = $preKnowledgeId " +
           "RETURN EXISTS((k1)-[:PRE_KNOWLEDGE]->(k2))")
    boolean existsPreKnowledgeRelationship(Long knowledgeId, Long preKnowledgeId);
    
    /**
     * 检查添加前置知识点关系后是否会导致循环依赖
     * @param knowledgeId 当前知识点ID
     * @param preKnowledgeId 前置知识点ID
     * @return 如果添加这个关系会导致循环依赖，返回true；否则返回false
     */
    @Query("MATCH (k1:Knowledge), (k2:Knowledge) " +
           "WHERE k1.nodeId = $knowledgeId AND k2.nodeId = $preKnowledgeId " +
           "RETURN EXISTS( " +
           "  (k2)-[:PRE_KNOWLEDGE*1..]->(k1) " +
           ")")
    boolean wouldCreateCyclicDependency(Long knowledgeId, Long preKnowledgeId);
    
    /**
     * 查询知识点所属课程信息
     * @param knowledgeId 知识点ID
     * @return 所属课程节点
     */
    @Query("MATCH (c:Course)-[:COURSE_KNOWLEDGE]->(k:Knowledge) WHERE k.nodeId = $knowledgeId RETURN c")
    CourseNode findCourseByKnowledgeId(Long knowledgeId);
    
    /**
     * 查询知识点的ID及其所属课程ID
     * @param knowledgeId 知识点ID
     * @return 课程ID
     */
    @Query("MATCH (c:Course)-[:COURSE_KNOWLEDGE]->(k:Knowledge) WHERE k.nodeId = $knowledgeId RETURN c.nodeId")
    Long findCourseIdByKnowledgeId(Long knowledgeId);

    /**
     * 根据组件ID查找关联的知识点，返回完整的知识点信息
     * @param componentId 组件ID
     * @return 关联的知识点列表（包含完整信息）
     */
    @Query("MATCH (cmp:Component)-[r:RELATED]->(k:Knowledge) " +
           "MATCH (c:Course)-[:COURSE_KNOWLEDGE]->(k) " + 
           "WHERE cmp.nodeId = $componentId " +
           "RETURN k, c.nodeId as courseId")
    Set<KnowledgeNode> findCompleteKnowledgeByComponentId(Long componentId);
} 